#include "stdafx.h"
#include "futil.h"

#pragma warning(disable: 4996)

int WriteBitmapHeader(BYTE *Buffer, int Width, int Height)
{
	BITMAPFILEHEADER *bmpfheader=(BITMAPFILEHEADER *)Buffer;
	BITMAPINFO *bmpinfo=(BITMAPINFO *)(((char*)bmpfheader)+14);
	int i,w;
	memset(bmpfheader,0,0x500);
	bmpfheader->bfType =19778;
	w = ((Width+3)/4)*4*Height+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFO)+255*sizeof(RGBQUAD);
	memcpy((void*)(((char*)bmpfheader)+2), &w, 4);
	//bmpfheader->bfOffBits;
	w= sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFO)+255*sizeof(RGBQUAD);
	memcpy((void*)(((char*)bmpfheader)+10), &w, 4);
	bmpinfo->bmiHeader.biWidth=Width;
	bmpinfo->bmiHeader.biHeight=Height;
	bmpinfo->bmiHeader.biBitCount=8;
	bmpinfo->bmiHeader.biClrUsed=0;
	bmpinfo->bmiHeader.biSize=sizeof(bmpinfo->bmiHeader);
	bmpinfo->bmiHeader.biPlanes=1;
	bmpinfo->bmiHeader.biSizeImage=((Width+3)/4)*4*Height;
	for(i=1;i<256;i++)
	{
		bmpinfo->bmiColors[i].rgbBlue=i;
		bmpinfo->bmiColors[i].rgbGreen=i;
		bmpinfo->bmiColors[i].rgbRed=i;
	}
	return sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD);
}

int WriteBitmap(BYTE *buffer, int Width, int Height, char *file)
{
	FILE *f=fopen(file, "wb");
	if(f)
	{
		unsigned char Buffer[0x500];
		int i, w=WriteBitmapHeader(Buffer, Width, Height);
		fwrite(Buffer, w, 1, f);
		w = ((Width+3)/4)*4;
		buffer+=Width*(Height-1);
		for(i=0; i<Height; i++)
		{
			fwrite(buffer, Width, 1, f);
			if(w-Width)
				fwrite(buffer, w-Width, 1, f);
			buffer-=Width;
		}
		fclose(f);
		return Width*Height;
	}
	return 0;
}

BYTE *LoadFile(const char *FileName, int *size)
{
	BYTE *data=NULL;
	FILE *f=fopen(FileName, "rb"); 
	long s;
	if(!f) return 0;
	fseek(f,0,SEEK_END);
	s=ftell(f);
	if(s>0)
	{
		fseek(f,0,SEEK_SET);
		data=(BYTE*)malloc(s);
		if (1>(long)fread(data, s, 1, f))
		{
			free(data);
			data=NULL;
		}
	}
	fclose(f);
	if(size) *size=s;
	return data;
}

int SaveToFile(const char *fileName, void *buffer, int size)
{
	FILE *f=fopen(fileName, "wb");
	if(f==NULL)
	{
		printf("Open file %s to write fail.\n", fileName);
		return 0;
	}
	fwrite(buffer, size, 1, f);
	fclose(f);
	return 1;
}

int ReadBitmap(BYTE *p, BYTE *buffer, int *Width, int *Height)
{
	BITMAPFILEHEADER *bmpfheader=(BITMAPFILEHEADER *)p;
	BITMAPINFO *bmpinfo=(BITMAPINFO *)(p+14);
	int i,w;
	if(!p) return 0;

	*Width = bmpinfo->bmiHeader.biWidth;
	*Height=bmpinfo->bmiHeader.biHeight;
	if((bmpfheader->bfType ==19778) && (bmpinfo->bmiHeader.biCompression==0) &&
		(bmpinfo->bmiHeader.biBitCount==8))
	{
		if(bmpinfo->bmiHeader.biClrUsed==0) bmpinfo->bmiHeader.biClrUsed=256;
		if(bmpinfo->bmiHeader.biClrUsed!=256) return 0;
		p+=0x436;
		w = ((*Width+3)/4)*4;
		p+=w*(*Height-1);
		if(buffer)
			for(i=0; i<(int)*Height; i++)
			{
				memcpy(buffer, p, *Width);
				buffer+=*Width;
				p-=w;
			}
	}
	else
	{
		return 0;
	}
	return *Width**Height;
}

int LoadBitmapFile(const char *FileName, BYTE *buffer, int *Width, int *Height)
{
	unsigned char *p=LoadFile(FileName, NULL);
	int res=ReadBitmap(p, buffer, Width, Height);
	free(p);
	return res;
}

int DumpData(BYTE *data, int dataSize)
{
	static char Hex[17]="0123456789ABCDEF";
	int i, linec=0;
	char line[20];
	printf("Dump Data: Size=%d\n", dataSize);
	for(i=0; i<dataSize;i++)
	{
		char HexData[3];
		HexData[0]=Hex[data[i]>>4]; HexData[1]=Hex[data[i]&0x0F]; HexData[2]=0;
		if(linec==0) printf("  ");
		printf("%s ", HexData);
		if(data[i]>=0x20 && data[i]<0xFF)
			line[linec]=data[i];
		else
			line[linec]='.';
		if(++linec>=16)
		{
			line[linec]=0;
			printf("  %s\n", line);
			linec=0;
		}
	}
	if(linec)
	{
		for(i=0;i<16-linec;i++) printf("   ");
		line[linec]=0;
		printf("  %s\n",line);
	}
	return 0;
}

HBITMAP BuildImage(BYTE *image, int width, int height)
{
	static HBITMAP pic;
	static CClientDC dc(NULL);

	BYTE info[256 * 4 + 40], *colors;
	BITMAPINFOHEADER *header  = (BITMAPINFOHEADER*)info;

	header -> biSize          = 40;
	header -> biHeight        = height;
	header -> biWidth         = width;
	header -> biPlanes        = 1;
	header -> biCompression   = 0;
	header -> biSizeImage     = width * height;
	header -> biXPelsPerMeter = 0;
	header -> biYPelsPerMeter = 0;
	header -> biClrImportant  = 0;
	header -> biBitCount      = 8;
	header -> biClrUsed       = 256;

	colors = info + 40;
	for(int i = 0; i < 256; i++)
	{
		*colors++ = i;
		*colors++ = i;
		*colors++ = i;
		*colors++ = 0;
	}
	
	if(pic)
		DeleteObject(pic);

	void *ptr;
//	CClientDC dc(NULL);
	pic = CreateDIBSection(dc.m_hDC, (BITMAPINFO*)info, DIB_RGB_COLORS, &ptr, NULL, 0);

	for(int i = 0; i < height; i++)
	{
		memcpy((char *)ptr+i*width, image+(height-i-1)*width, width);
	}

	return pic;
}
